<?php
/**
 * OrderController.php
 *
 * @copyright  2022 beikeshop.com - All Rights Reserved
 * @link       https://beikeshop.com
 * @author     Edward Yang <yangjin@guangda.work>
 * @created    2022-07-05 10:45:26
 * @modified   2022-07-05 10:45:26
 */

namespace Beike\Admin\Http\Controllers;

use Barryvdh\DomPDF\Facade\Pdf;
use Beike\Admin\Http\Resources\ExportIncomingWord;
use Beike\Admin\Http\Resources\ExportQuotationWord;
use Beike\Admin\Http\Resources\OrderProductSimple;
use Beike\Admin\Http\Resources\OrderSimple;
use Beike\Models\Order;
use Beike\Models\OrderProduct;
use Beike\Models\OrderShipment;
use Beike\Models\OrderTotal;
use Beike\Repositories\OrderLogRepo;
use Beike\Repositories\OrderProductRepo;
use Beike\Repositories\OrderRepo;
use Beike\Services\ShipmentService;
use Beike\Services\StateMachineService;
use Beike\Shop\Http\Resources\Account\OrderSimpleList;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use TCPDF;

class OrderController extends Controller
{
    /**
     * 获取订单列表
     *
     * @param Request $request
     * @return mixed
     * @throws \Exception
     */
    public function index(Request $request)
    {
        $orders = OrderRepo::filterOrders($request->all());
        $data   = [
            'orders'          => OrderSimpleList::collection($orders),
            'statuses'        => StateMachineService::getAllStatuses(),
            'type'            => 'index',
        ];
        $data = hook_filter('admin.order.index.data', $data);

        return view('admin::pages.orders.index', $data);
    }

    /**
     * 获取订单回收站列表
     *
     * @param Request $request
     * @return mixed
     * @throws \Exception
     */
    public function trashed(Request $request)
    {
        $requestData            = $request->all();
        $requestData['trashed'] = true;
        $orders                 = OrderRepo::filterOrders($requestData);
        $data                   = [
            'orders'          => OrderSimpleList::collection($orders),
            'statuses'        => StateMachineService::getAllStatuses(),
            'type'            => 'trashed',
        ];
        $data = hook_filter('admin.order.trashed.data', $data);

        return view('admin::pages.orders.index', $data);
    }

    /**
     * 导出订单列表
     *
     * @param Request $request
     * @return mixed
     * @throws \Exception
     */
    public function export(Request $request)
    {
        try {
            $orders = OrderRepo::filterAll($request->all());
            $items  = OrderSimple::collection($orders)->jsonSerialize();
            $items  = hook_filter('admin.order.export.data', $items);


            return $this->downloadCsv('orders', $items, 'order');
        } catch (\Exception $e) {
            return redirect(admin_route('orders.index'))->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * 导出订单商品列表
     *
     * @param Request $request
     * @return mixed
     * @throws \Exception
     */
    public function exportOrderGoods(Request $request)
    {
        try {
            $orders = OrderProductRepo::filterAll($request->all());
            $items  = OrderProductSimple::collection($orders)->jsonSerialize();
            $items  = hook_filter('admin.order.export_order_goods.data', $items);

            return $this->downloadCsv('orders_goods', $items, 'order');
        } catch (\Exception $e) {
            return redirect(admin_route('orders.index'))->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * 导出 订单 报价文档 表格
     *
     * @param Request $request
     * @return mixed
     * @throws \Exception
     */
    public function exportQuotationWord(Request $request)
    {
        try {
            $orders = OrderProductRepo::filterAll($request->all());
            $items  = ExportQuotationWord::collection($orders)->jsonSerialize();
            $items  = hook_filter('admin.order.export_quotation_word.data', $items);
            $prices = array_column($items, 'total');
            $totalPrice = currency_format(array_sum($prices));
            $quantitys = array_column($items, 'quantity_en');
            $totalQuantity = array_sum($quantitys);
            $append = [
                ["Total:",'','','',$totalQuantity,$totalPrice]
            ];
            foreach ($items as $key => $value){
                if(isset($value['total'])){
                    unset($items[$key]['total']);
                }
            }

            return $this->downloadCsv('quotation_word', $items, 'product',$append);
        } catch (\Exception $e) {
            return redirect(admin_route('orders.index'))->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * 导出 订单 入货文档 表格
     *
     * @param Request $request
     * @return mixed
     * @throws \Exception
     */
    public function exportIncomingWord(Request $request)
    {
        try {
            $orders = OrderProductRepo::filterAll($request->all());
            $items  = ExportIncomingWord::collection($orders)->jsonSerialize();
            $items  = hook_filter('admin.order.export_incoming_word.data', $items);

            $prices = array_column($items, 'total_tt');
            $totalPrice = currency_format(array_sum($prices));
            $quantitys = array_column($items, 'number');
            $totalQuantity = array_sum($quantitys);
            $customer_message = $items[0]['customer_name_en']??"";
            $customer_message = $items[0]['telephone_en']?($customer_message?$customer_message.":".$items[0]['telephone_en']:''):"";
            $append = [
                [trans('product.total'),'','','',$totalQuantity,$totalPrice],
                [$items[0]['shipping_address_en']??'','',$customer_message]
            ];
            foreach ($items as $key => $value){
                unset($items[$key]['total_tt']);
                unset($items[$key]['customer_name_en']);
                unset($items[$key]['telephone_en']);
                unset($items[$key]['shipping_address_en']);
            }

            return $this->downloadCsv('incoming_word', $items, 'product',$append);
        } catch (\Exception $e) {
            return redirect(admin_route('orders.index'))->withErrors(['error' => $e->getMessage()]);
        }
    }

    /**
     * 查看单个订单
     *
     * @param Request $request
     * @param Order   $order
     * @return mixed
     * @throws \Exception
     */
    public function show(Request $request, Order $order)
    {
        $order->load(['orderTotals', 'orderHistories', 'orderShipments', 'orderPayments']);
        $data             = hook_filter('admin.order.show.data', ['order' => $order, 'html_items' => []]);
        $data['statuses'] = StateMachineService::getInstance($order)->nextBackendStatuses();
        hook_action('admin.order.show.after', $data);

        return view('admin::pages.orders.form', $data);
    }

    /**
     * 查看 单个订单 的报价文档
     *
     * @param Request $request
     * @param Order   $order
     * @return mixed
     * @throws \Exception
     */
    public function quotationWord(Request $request, Order $order)
    {
        $order->load(['orderTotals', 'orderHistories']);
        $data   = hook_filter('admin.order.quotation_word.data', ['order' => $order]);

        return view('admin::pages.orders.quotation_word', $data);
    }

    /**
     * 查看 单个订单 的 入货文档
     *
     * @param Request $request
     * @param Order   $order
     * @return mixed
     * @throws \Exception
     */
    public function incomingWord(Request $request, Order $order)
    {
        $order->load(['orderTotals', 'orderHistories', 'orderShipments']);
        $data   = hook_filter('admin.order.incoming_word.data', ['order' => $order]);

        return view('admin::pages.orders.incoming_word', $data);
    }


    /**
     * 导出 订单 入货文档 pdf
     * @param Request $request
     * @param Order $order
     */
    public function exportIncomingWordPdf(Request $request, Order $order){
        $order->load(['orderTotals', 'orderHistories', 'orderShipments']);

        $tbl = '<div class="div001"><table class="table" align="center"><thead><tr>';
        $tbl .= '<th>'.trans('product.imagen').'</th>';
        $tbl .= '<th>'.trans('product.product_description').'</th>';
        $tbl .= '<th>'.trans('product.sku').'</th>';
        $tbl .= '<th>'.trans('product.number').'</th>';
        $tbl .= '<th>'.trans('product.unit_price').'</th>';
        $tbl .= '<th class="text-end">'.trans('product.total').'</th>';
        $tbl .= '<th>'.trans('product.remark').'</th>';
        $tbl .= '</tr></thead><tbody>';

        foreach ($order->orderShipments as $key => $shipment){
            $tbl .= '<tr>';
            $tbl .= '<td>'.$shipment->express_company.'</td>';
            $tbl .= '<td>'.$shipment->express_number.'</td>';
            $tbl .= '<td></td>';
            $tbl .= '<td></td>';
            $tbl .= '<td></td>';
            $tbl .= '<td></td>';
            $tbl .= '<td></td>';
            $tbl .= '</tr>';
        }

        foreach ($order->orderProducts as $key => $product){
            $tbl .= '<tr>';
            $tbl .= '<td><div class="d-flex align-items-center">
                      <div class="wh-div"><img src="'.$product->image.'" class="img-lqh"></div>
                    </div></td>';
            $tbl .= '<td>'.$product->name.'</td>';
            $tbl .= '<td>'.$product->product_sku.'</td>';
            $tbl .= '<td>'.$product->quantity.'</td>';
            $tbl .= '<td>'.currency_format($product->price, $order->currency_code, $order->currency_value).'</td>';
            $tbl .= '<td class="text-end">'.currency_format($product->price * $product->quantity, $order->currency_code, $order->currency_value).'</td>';
            $tbl .= ($key == 0)?'<td>'.$order->remark.'</td>':'<td></td>';
            $tbl .= '</tr>';
        }
        $tbl .= '</tbody><tfoot>';
        foreach ($order->orderTotals as $orderTotal){
            $tbl .= '<tr>';
            $tbl .= '<td colspan="5" class="text-end" align="left">'.$orderTotal->title.'</td>';
            $tbl .= '<td class="text-end"><span class="fw-bold">'.currency_format($orderTotal->value, $order->currency_code, $order->currency_value).'</span></td>';
            $tbl .= '</tr>';
        }

        $tbl .= '<tr>';
        $address = $order->payment_zone.$order->payment_city.$order->payment_address_1.$order->payment_address_2;
        $tbl .= '<td colspan="4" class="text-end" align="left">'.$address.'</td>';
        $tbl .= '<td class="text-end" colspan="3"><span class="fw-bold">'.$order->payment_customer_name.($order->payment_telephone?':'.$order->payment_telephone:'').'</span></td>';
        $tbl .= '</tr>';
        $tbl .= '</tfoot></table></div>';

        return $this->downloadCPDf($order,trans('admin/order.orders_incoming_word'),$tbl);
    }

    /**
     * 导出 订单 入货文档 pdf
     * @param Request $request
     * @param Order $order
     */
    public function exportQuotationWordPdf(Request $request, Order $order){
        $order->load(['orderTotals', 'orderHistories']);

        $tbl = '<div class="div001"><table class="table" align="center"><thead><tr>';
        $tbl .= '<th>'.trans('product.imagen_en').'</th>';
        $tbl .= '<th>'.trans('product.product_description_en').'</th>';
        $tbl .= '<th>'.trans('product.sku').'</th>';
        $tbl .= '<th>'.trans('product.precio_en').'</th>';
        $tbl .= '<th>'.trans('product.quantity_en').'</th>';
        $tbl .= '<th class="text-end">'.trans('product.total_en').'</th>';
        $tbl .= '</tr></thead><tbody>';
        foreach ($order->orderProducts as  $product){
            $tbl .= '<tr>';
            $tbl .= '<td><div class="d-flex align-items-center">
                      <div class="wh-div"><img src="'.$product->image.'" class="img-lqh"></div>
                    </div></td>';
            $tbl .= '<td>'.$product->name.'</td>';
            $tbl .= '<td>'.$product->product_sku.'</td>';
            $tbl .= '<td>'.currency_format($product->price, $order->currency_code, $order->currency_value).'</td>';
            $tbl .= '<td>'.$product->quantity.'</td>';
            $tbl .= '<td class="text-end">'.currency_format($product->price * $product->quantity, $order->currency_code, $order->currency_value).'</td>';
            $tbl .= '</tr>';
        }
        $tbl .= '</tbody><tfoot>';
        foreach ($order->orderTotals as $orderTotal){
            $tbl .= '<tr>';
            $tbl .= '<td colspan="5" class="text-end" align="left">'.$orderTotal->title.'</td>';
            $tbl .= '<td class="text-end"><span class="fw-bold">'.currency_format($orderTotal->value, $order->currency_code, $order->currency_value).'</span></td>';
            $tbl .= '</tr>';
        }
        $tbl .= '</tfoot></table></div>';

        return $this->downloadCPDf($order,trans('admin/order.orders_quotation_word'),$tbl);
    }

    /**
     * 更新订单状态,添加订单更新日志
     *
     * @param Request $request
     * @param Order   $order
     * @return array
     * @throws \Throwable
     */
    public function updateStatus(Request $request, Order $order)
    {
        $status  = $request->get('status');
        $comment = $request->get('comment');
        $notify  = $request->get('notify');

        $shipment = ShipmentService::handleShipment(\request('express_code'), \request('express_number'));

        $stateMachine = new StateMachineService($order);
        $stateMachine->setShipment($shipment)->changeStatus($status, $comment, $notify);

        $orderStatusData = $request->all();

        hook_action('admin.order.update_status.after', $orderStatusData);

        return json_success(trans('common.updated_success'));
    }

    /**
     * 更新订单信息，报价
     *
     * @param Request $request
     * @param Order   $order
     * @return array
     * @throws \Throwable
     */
    public function update(Request $request, Order $order)
    {
        $type  = $request->get('type');
        $update_data  = $request->get('update_data');
        $product_id = $request->get('product_id');


        $is_update_order = true;
        $is_update_order_price = true;
        $data = [];
        $data_log = [];
        $log_type = 'order_product';
        switch ($type) {
            case 'name':
                $data['name'] = $update_data;
                $is_update_order_price = false;
                break;
            case 'product_sku':
                $data['product_sku'] = $update_data;
                $is_update_order_price = false;
                break;
            case 'price':
                $data['price'] = $update_data;
                break;
            case 'quantity':
                $data['quantity'] = $update_data;
                break;
            case 'price_all':
                $log_type = 'order';
                $is_update_order = false;
                break;
        }


        DB::beginTransaction();
        //更新订单商品
        $chang_sub_total = 0;
        if($is_update_order){
            $order_products_model = OrderProduct::query()
                ->select(['id','quantity','price','product_sku','name'])
                ->where('product_id','=',$product_id)
                ->where('order_id','=',$order->id);
            $order_product_one = objectToArray($order_products_model->first());
            if($order_product_one && $data){
                if($type == 'price'){
                    $new_total = $order_product_one['quantity'] * $update_data;
                }else if($type == 'quantity'){
                    $new_total = $update_data * $order_product_one['price'];
                }
                $chang_sub_total = $new_total - $order_product_one['price']*$order_product_one['quantity'];
                $data_log[] = [
                    'key_id'        =>  $order_product_one['id'],
                    'type'          =>  $log_type,
                    'new_value'     =>  $update_data,
                    'old_value'     =>  $order_product_one[$type],
                    'update_field'  =>  $type
                ];

                $order_products_model->update($data);
            }else{
                DB::rollBack();
                return json_fail(("找不到订单记录或者数据为空"));
            }
        }

        //更新订单价格表
        $new_order_total = 0;//订单的总价格
        if($is_update_order_price){
            $order_total_list = OrderTotal::query()
                ->where('order_id','=',$order->id)
                ->whereIn('code',["order_total",'sub_total'])
                ->get();

            $list = objectToArray($order_total_list);
            if($list && $chang_sub_total){
                foreach ($list as $value){
                    $new_value = $value['value'] + $chang_sub_total;
                    $data_log[] = [
                        'type'          =>  'order_total',
                        'key_id'        =>  $value['id'],
                        'new_value'     =>  $new_value,
                        'old_value'     =>  $value['value'],
                        'update_field'  =>  $value['code']
                    ];
                    if($value['code'] == 'order_total'){
                        $new_order_total = $new_value;
                    }
                    OrderTotal::query()
                        ->where('id','=',$value['id'])
                        ->update(['value'=>$new_value]);
                }
            }else{
                DB::rollBack();
                return json_fail(("找不到订单金额构成记录或者数据为空"));
            }
        }

        //更新订单表
        if($new_order_total){
            $data_log[] = [
                'type'          =>  'order',
                'key_id'        =>  $order->id,
                'new_value'     =>  $new_order_total,
                'old_value'     =>  $order->total,
                'update_field'  =>  'total'
            ];
            Order::query()
                ->where('id','=',$order->id)
                ->update(['total'=>$new_order_total]);
        }


        if($data_log){
            OrderLogRepo::createLogs($data_log);
        }
        //日志
        DB::commit();


        $orderData = $request->all();
        hook_action('admin.order.update.after', $orderData);

        return json_success(trans('common.updated_success'));
    }

    public function updateTotal(Request $request, $order_total_id){
        $type  = $request->get('type');
        $value  = $request->get('value');

        $order_total = OrderTotal::query()->find($order_total_id);

        $data_log = [];
        $change_total = 0;
        $new_total = 0;
        if($order_total->value == $value){
            return json_fail(("运费没有变化，不用修改"));
        }else{
            $data_log[] = [
                'type'          =>  'order_total',
                'key_id'        =>  $order_total->id,
                'new_value'     =>  $value,
                'old_value'     =>  $order_total->value,
                'update_field'  =>  'value'
            ];
            $change_total = $value - $order_total->value;
            $order_total->value = $value;
            $order_total->saveOrFail();


            $order_total_one = OrderTotal::query()
                ->where('order_id','=',$order_total->order_id)
                ->where('code','=','order_total')
                ->first();
            if($order_total_one){
                $new_total = $change_total + $order_total_one->value;
                $data_log[] = [
                    'type'          =>  'order_total',
                    'key_id'        =>  $order_total_one->id,
                    'new_value'     =>  $new_total,
                    'old_value'     =>  $order_total_one->value,
                    'update_field'  =>  'value'
                ];
                OrderTotal::query()
                    ->where('id','=',$order_total_one->id)
                    ->update(['value'=>$new_total]);

            }
        }

        //更新订单表
        if($change_total != 0){
            Order::query()
                ->where('id','=',$order_total->order_id)
                ->update(['total'=>$new_total]);
            $data_log[] = [
                'type'          =>  'order',
                'key_id'        =>  $order_total->order_id,
                'new_value'     =>  $new_total,
                'old_value'     =>  $new_total - $change_total,
                'update_field'  =>  'total',
            ];
        }

        if($data_log){
            OrderLogRepo::createLogs($data_log);
        }
        return json_success(trans('common.updated_success'));
    }

    /**
     * 更新发货信息
     */
    public function updateShipment(Request $request, Order $order, int $orderShipmentId): JsonResponse
    {
        $data          = $request->all();
        $orderShipment = OrderShipment::query()->where('order_id', $order->id)->findOrFail($orderShipmentId);
        ShipmentService::updateShipment($orderShipment, $data);
        hook_action('admin.order.update_shipment.after', [
            'request_data' => $data,
            'shipment'     => $orderShipment,
        ]);

        return json_success(trans('common.updated_success'));
    }

    public function destroy(Request $request, Order $order)
    {
        $order->delete();
        hook_action('admin.order.destroy.after', $order);

        return json_success(trans('common.deleted_success'));
    }

    public function restore(Request $request)
    {
        $id = $request->id ?? 0;
        Order::withTrashed()->find($id)->restore();

        hook_action('admin.product.restore.after', $id);

        return ['success' => true];
    }
}
